1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.primitives;
18  
19  import static com.google.common.base.Preconditions.checkArgument;
20  import static com.google.common.base.Preconditions.checkElementIndex;
21  import static com.google.common.base.Preconditions.checkNotNull;
22  import static com.google.common.base.Preconditions.checkPositionIndexes;
23  
24  import com.google.common.annotations.Beta;
25  import com.google.common.annotations.GwtCompatible;
26  import com.google.common.base.Converter;
27  
28  import java.io.Serializable;
29  import java.util.AbstractList;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.Comparator;
33  import java.util.List;
34  import java.util.RandomAccess;
35  
36  /**
37   * Static utility methods pertaining to {@code short} primitives, that are not
38   * already found in either {@link Short} or {@link Arrays}.
39   *
40   * <p>See the Guava User Guide article on <a href=
41   * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
42   * primitive utilities</a>.
43   *
44   * @author Kevin Bourrillion
45   * @since 1.0
46   */
47  @GwtCompatible(emulated = true)
48  public final class Shorts {
49    private Shorts() {}
50  
51    /**
52     * The number of bytes required to represent a primitive {@code short}
53     * value.
54     */
55    public static final int BYTES = Short.SIZE / Byte.SIZE;
56  
57    /**
58     * The largest power of two that can be represented as a {@code short}.
59     *
60     * @since 10.0
61     */
62    public static final short MAX_POWER_OF_TWO = 1 << (Short.SIZE - 2);
63  
64    /**
65     * Returns a hash code for {@code value}; equal to the result of invoking
66     * {@code ((Short) value).hashCode()}.
67     *
68     * @param value a primitive {@code short} value
69     * @return a hash code for the value
70     */
71    public static int hashCode(short value) {
72      return value;
73    }
74  
75    /**
76     * Returns the {@code short} value that is equal to {@code value}, if
77     * possible.
78     *
79     * @param value any value in the range of the {@code short} type
80     * @return the {@code short} value that equals {@code value}
81     * @throws IllegalArgumentException if {@code value} is greater than {@link
82     *     Short#MAX_VALUE} or less than {@link Short#MIN_VALUE}
83     */
84    public static short checkedCast(long value) {
85      short result = (short) value;
86      if (result != value) {
87        // don't use checkArgument here, to avoid boxing
88        throw new IllegalArgumentException("Out of range: " + value);
89      }
90      return result;
91    }
92  
93    /**
94     * Returns the {@code short} nearest in value to {@code value}.
95     *
96     * @param value any {@code long} value
97     * @return the same value cast to {@code short} if it is in the range of the
98     *     {@code short} type, {@link Short#MAX_VALUE} if it is too large,
99     *     or {@link Short#MIN_VALUE} if it is too small
100    */
101   public static short saturatedCast(long value) {
102     if (value > Short.MAX_VALUE) {
103       return Short.MAX_VALUE;
104     }
105     if (value < Short.MIN_VALUE) {
106       return Short.MIN_VALUE;
107     }
108     return (short) value;
109   }
110 
111   /**
112    * Compares the two specified {@code short} values. The sign of the value
113    * returned is the same as that of {@code ((Short) a).compareTo(b)}.
114    *
115    * <p><b>Note for Java 7 and later:</b> this method should be treated as
116    * deprecated; use the equivalent {@link Short#compare} method instead.
117    *
118    * @param a the first {@code short} to compare
119    * @param b the second {@code short} to compare
120    * @return a negative value if {@code a} is less than {@code b}; a positive
121    *     value if {@code a} is greater than {@code b}; or zero if they are equal
122    */
123   public static int compare(short a, short b) {
124     return a - b; // safe due to restricted range
125   }
126 
127   /**
128    * Returns {@code true} if {@code target} is present as an element anywhere in
129    * {@code array}.
130    *
131    * @param array an array of {@code short} values, possibly empty
132    * @param target a primitive {@code short} value
133    * @return {@code true} if {@code array[i] == target} for some value of {@code
134    *     i}
135    */
136   public static boolean contains(short[] array, short target) {
137     for (short value : array) {
138       if (value == target) {
139         return true;
140       }
141     }
142     return false;
143   }
144 
145   /**
146    * Returns the index of the first appearance of the value {@code target} in
147    * {@code array}.
148    *
149    * @param array an array of {@code short} values, possibly empty
150    * @param target a primitive {@code short} value
151    * @return the least index {@code i} for which {@code array[i] == target}, or
152    *     {@code -1} if no such index exists.
153    */
154   public static int indexOf(short[] array, short target) {
155     return indexOf(array, target, 0, array.length);
156   }
157 
158   // TODO(kevinb): consider making this public
159   private static int indexOf(
160       short[] array, short target, int start, int end) {
161     for (int i = start; i < end; i++) {
162       if (array[i] == target) {
163         return i;
164       }
165     }
166     return -1;
167   }
168 
169   /**
170    * Returns the start position of the first occurrence of the specified {@code
171    * target} within {@code array}, or {@code -1} if there is no such occurrence.
172    *
173    * <p>More formally, returns the lowest index {@code i} such that {@code
174    * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
175    * the same elements as {@code target}.
176    *
177    * @param array the array to search for the sequence {@code target}
178    * @param target the array to search for as a sub-sequence of {@code array}
179    */
180   public static int indexOf(short[] array, short[] target) {
181     checkNotNull(array, "array");
182     checkNotNull(target, "target");
183     if (target.length == 0) {
184       return 0;
185     }
186 
187     outer:
188     for (int i = 0; i < array.length - target.length + 1; i++) {
189       for (int j = 0; j < target.length; j++) {
190         if (array[i + j] != target[j]) {
191           continue outer;
192         }
193       }
194       return i;
195     }
196     return -1;
197   }
198 
199   /**
200    * Returns the index of the last appearance of the value {@code target} in
201    * {@code array}.
202    *
203    * @param array an array of {@code short} values, possibly empty
204    * @param target a primitive {@code short} value
205    * @return the greatest index {@code i} for which {@code array[i] == target},
206    *     or {@code -1} if no such index exists.
207    */
208   public static int lastIndexOf(short[] array, short target) {
209     return lastIndexOf(array, target, 0, array.length);
210   }
211 
212   // TODO(kevinb): consider making this public
213   private static int lastIndexOf(
214       short[] array, short target, int start, int end) {
215     for (int i = end - 1; i >= start; i--) {
216       if (array[i] == target) {
217         return i;
218       }
219     }
220     return -1;
221   }
222 
223   /**
224    * Returns the least value present in {@code array}.
225    *
226    * @param array a <i>nonempty</i> array of {@code short} values
227    * @return the value present in {@code array} that is less than or equal to
228    *     every other value in the array
229    * @throws IllegalArgumentException if {@code array} is empty
230    */
231   public static short min(short... array) {
232     checkArgument(array.length > 0);
233     short min = array[0];
234     for (int i = 1; i < array.length; i++) {
235       if (array[i] < min) {
236         min = array[i];
237       }
238     }
239     return min;
240   }
241 
242   /**
243    * Returns the greatest value present in {@code array}.
244    *
245    * @param array a <i>nonempty</i> array of {@code short} values
246    * @return the value present in {@code array} that is greater than or equal to
247    *     every other value in the array
248    * @throws IllegalArgumentException if {@code array} is empty
249    */
250   public static short max(short... array) {
251     checkArgument(array.length > 0);
252     short max = array[0];
253     for (int i = 1; i < array.length; i++) {
254       if (array[i] > max) {
255         max = array[i];
256       }
257     }
258     return max;
259   }
260 
261   /**
262    * Returns the values from each provided array combined into a single array.
263    * For example, {@code concat(new short[] {a, b}, new short[] {}, new
264    * short[] {c}} returns the array {@code {a, b, c}}.
265    *
266    * @param arrays zero or more {@code short} arrays
267    * @return a single array containing all the values from the source arrays, in
268    *     order
269    */
270   public static short[] concat(short[]... arrays) {
271     int length = 0;
272     for (short[] array : arrays) {
273       length += array.length;
274     }
275     short[] result = new short[length];
276     int pos = 0;
277     for (short[] array : arrays) {
278       System.arraycopy(array, 0, result, pos, array.length);
279       pos += array.length;
280     }
281     return result;
282   }
283 
284   private static final class ShortConverter
285       extends Converter<String, Short> implements Serializable {
286     static final ShortConverter INSTANCE = new ShortConverter();
287 
288     @Override
289     protected Short doForward(String value) {
290       return Short.decode(value);
291     }
292 
293     @Override
294     protected String doBackward(Short value) {
295       return value.toString();
296     }
297 
298     @Override
299     public String toString() {
300       return "Shorts.stringConverter()";
301     }
302 
303     private Object readResolve() {
304       return INSTANCE;
305     }
306     private static final long serialVersionUID = 1;
307   }
308 
309   /**
310    * Returns a serializable converter object that converts between strings and
311    * shorts using {@link Short#decode} and {@link Short#toString()}.
312    *
313    * @since 16.0
314    */
315   @Beta
316   public static Converter<String, Short> stringConverter() {
317     return ShortConverter.INSTANCE;
318   }
319 
320   /**
321    * Returns an array containing the same values as {@code array}, but
322    * guaranteed to be of a specified minimum length. If {@code array} already
323    * has a length of at least {@code minLength}, it is returned directly.
324    * Otherwise, a new array of size {@code minLength + padding} is returned,
325    * containing the values of {@code array}, and zeroes in the remaining places.
326    *
327    * @param array the source array
328    * @param minLength the minimum length the returned array must guarantee
329    * @param padding an extra amount to "grow" the array by if growth is
330    *     necessary
331    * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
332    *     negative
333    * @return an array containing the values of {@code array}, with guaranteed
334    *     minimum length {@code minLength}
335    */
336   public static short[] ensureCapacity(
337       short[] array, int minLength, int padding) {
338     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
339     checkArgument(padding >= 0, "Invalid padding: %s", padding);
340     return (array.length < minLength)
341         ? copyOf(array, minLength + padding)
342         : array;
343   }
344 
345   // Arrays.copyOf() requires Java 6
346   private static short[] copyOf(short[] original, int length) {
347     short[] copy = new short[length];
348     System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
349     return copy;
350   }
351 
352   /**
353    * Returns a string containing the supplied {@code short} values separated
354    * by {@code separator}. For example, {@code join("-", (short) 1, (short) 2,
355    * (short) 3)} returns the string {@code "1-2-3"}.
356    *
357    * @param separator the text that should appear between consecutive values in
358    *     the resulting string (but not at the start or end)
359    * @param array an array of {@code short} values, possibly empty
360    */
361   public static String join(String separator, short... array) {
362     checkNotNull(separator);
363     if (array.length == 0) {
364       return "";
365     }
366 
367     // For pre-sizing a builder, just get the right order of magnitude
368     StringBuilder builder = new StringBuilder(array.length * 6);
369     builder.append(array[0]);
370     for (int i = 1; i < array.length; i++) {
371       builder.append(separator).append(array[i]);
372     }
373     return builder.toString();
374   }
375 
376   /**
377    * Returns a comparator that compares two {@code short} arrays
378    * lexicographically. That is, it compares, using {@link
379    * #compare(short, short)}), the first pair of values that follow any
380    * common prefix, or when one array is a prefix of the other, treats the
381    * shorter array as the lesser. For example, {@code [] < [(short) 1] <
382    * [(short) 1, (short) 2] < [(short) 2]}.
383    *
384    * <p>The returned comparator is inconsistent with {@link
385    * Object#equals(Object)} (since arrays support only identity equality), but
386    * it is consistent with {@link Arrays#equals(short[], short[])}.
387    *
388    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
389    *     Lexicographical order article at Wikipedia</a>
390    * @since 2.0
391    */
392   public static Comparator<short[]> lexicographicalComparator() {
393     return LexicographicalComparator.INSTANCE;
394   }
395 
396   private enum LexicographicalComparator implements Comparator<short[]> {
397     INSTANCE;
398 
399     @Override
400     public int compare(short[] left, short[] right) {
401       int minLength = Math.min(left.length, right.length);
402       for (int i = 0; i < minLength; i++) {
403         int result = Shorts.compare(left[i], right[i]);
404         if (result != 0) {
405           return result;
406         }
407       }
408       return left.length - right.length;
409     }
410   }
411 
412   /**
413    * Returns an array containing each value of {@code collection}, converted to
414    * a {@code short} value in the manner of {@link Number#shortValue}.
415    *
416    * <p>Elements are copied from the argument collection as if by {@code
417    * collection.toArray()}.  Calling this method is as thread-safe as calling
418    * that method.
419    *
420    * @param collection a collection of {@code Number} instances
421    * @return an array containing the same values as {@code collection}, in the
422    *     same order, converted to primitives
423    * @throws NullPointerException if {@code collection} or any of its elements
424    *     is null
425    * @since 1.0 (parameter was {@code Collection<Short>} before 12.0)
426    */
427   public static short[] toArray(Collection<? extends Number> collection) {
428     if (collection instanceof ShortArrayAsList) {
429       return ((ShortArrayAsList) collection).toShortArray();
430     }
431 
432     Object[] boxedArray = collection.toArray();
433     int len = boxedArray.length;
434     short[] array = new short[len];
435     for (int i = 0; i < len; i++) {
436       // checkNotNull for GWT (do not optimize)
437       array[i] = ((Number) checkNotNull(boxedArray[i])).shortValue();
438     }
439     return array;
440   }
441 
442   /**
443    * Returns a fixed-size list backed by the specified array, similar to {@link
444    * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
445    * but any attempt to set a value to {@code null} will result in a {@link
446    * NullPointerException}.
447    *
448    * <p>The returned list maintains the values, but not the identities, of
449    * {@code Short} objects written to or read from it.  For example, whether
450    * {@code list.get(0) == list.get(0)} is true for the returned list is
451    * unspecified.
452    *
453    * @param backingArray the array to back the list
454    * @return a list view of the array
455    */
456   public static List<Short> asList(short... backingArray) {
457     if (backingArray.length == 0) {
458       return Collections.emptyList();
459     }
460     return new ShortArrayAsList(backingArray);
461   }
462 
463   @GwtCompatible
464   private static class ShortArrayAsList extends AbstractList<Short>
465       implements RandomAccess, Serializable {
466     final short[] array;
467     final int start;
468     final int end;
469 
470     ShortArrayAsList(short[] array) {
471       this(array, 0, array.length);
472     }
473 
474     ShortArrayAsList(short[] array, int start, int end) {
475       this.array = array;
476       this.start = start;
477       this.end = end;
478     }
479 
480     @Override public int size() {
481       return end - start;
482     }
483 
484     @Override public boolean isEmpty() {
485       return false;
486     }
487 
488     @Override public Short get(int index) {
489       checkElementIndex(index, size());
490       return array[start + index];
491     }
492 
493     @Override public boolean contains(Object target) {
494       // Overridden to prevent a ton of boxing
495       return (target instanceof Short)
496           && Shorts.indexOf(array, (Short) target, start, end) != -1;
497     }
498 
499     @Override public int indexOf(Object target) {
500       // Overridden to prevent a ton of boxing
501       if (target instanceof Short) {
502         int i = Shorts.indexOf(array, (Short) target, start, end);
503         if (i >= 0) {
504           return i - start;
505         }
506       }
507       return -1;
508     }
509 
510     @Override public int lastIndexOf(Object target) {
511       // Overridden to prevent a ton of boxing
512       if (target instanceof Short) {
513         int i = Shorts.lastIndexOf(array, (Short) target, start, end);
514         if (i >= 0) {
515           return i - start;
516         }
517       }
518       return -1;
519     }
520 
521     @Override public Short set(int index, Short element) {
522       checkElementIndex(index, size());
523       short oldValue = array[start + index];
524       // checkNotNull for GWT (do not optimize)
525       array[start + index] = checkNotNull(element);
526       return oldValue;
527     }
528 
529     @Override public List<Short> subList(int fromIndex, int toIndex) {
530       int size = size();
531       checkPositionIndexes(fromIndex, toIndex, size);
532       if (fromIndex == toIndex) {
533         return Collections.emptyList();
534       }
535       return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
536     }
537 
538     @Override public boolean equals(Object object) {
539       if (object == this) {
540         return true;
541       }
542       if (object instanceof ShortArrayAsList) {
543         ShortArrayAsList that = (ShortArrayAsList) object;
544         int size = size();
545         if (that.size() != size) {
546           return false;
547         }
548         for (int i = 0; i < size; i++) {
549           if (array[start + i] != that.array[that.start + i]) {
550             return false;
551           }
552         }
553         return true;
554       }
555       return super.equals(object);
556     }
557 
558     @Override public int hashCode() {
559       int result = 1;
560       for (int i = start; i < end; i++) {
561         result = 31 * result + Shorts.hashCode(array[i]);
562       }
563       return result;
564     }
565 
566     @Override public String toString() {
567       StringBuilder builder = new StringBuilder(size() * 6);
568       builder.append('[').append(array[start]);
569       for (int i = start + 1; i < end; i++) {
570         builder.append(", ").append(array[i]);
571       }
572       return builder.append(']').toString();
573     }
574 
575     short[] toShortArray() {
576       // Arrays.copyOfRange() is not available under GWT
577       int size = size();
578       short[] result = new short[size];
579       System.arraycopy(array, start, result, 0, size);
580       return result;
581     }
582 
583     private static final long serialVersionUID = 0;
584   }
585 }